<?php
/**
 * Created by PhpStorm.
 * User: krystal
 * Date: 2019/4/22
 * Time: 15:04
 */

namespace app\api\controller\v9;


use app\api\controller\v2\Auth;
use app\common\lib\AliOss;
use app\common\model\Recode;
use app\common\model\ZhunleCounselor;
use app\common\model\ZlAstr;
use app\common\model\ZlAstrInfoCheck;
use app\common\model\ZlAstrExercise;
use app\common\model\ZlAstrExerciseRecord;
use app\common\model\ZlAstrExerciseType;
use app\common\model\ZlTag;
use think\Cache;
use think\response\Json;
use app\common\lib\exception\ApiException;

/**
 * 咨询师相关接口
 * Class Counselor
 * @package app\api\controller\v10
 */
class Counselor extends Auth
{
    //TODO 咨询师插入数据时，删除用户缓存
    //TODO 进入提交审核接口时，修改认证状态未审核中

    protected $ExerciseNum;
    protected $ExerciseScore;
    protected $ExerciseTotalScore;
    protected $ExerciseTime;

    public function _initialize()
    {
        parent::_initialize();
        $this->ExerciseNum = 2;//考核次数
        $this->ExerciseScore = 60;//考核及格分数
        $this->ExerciseTotalScore = 100;//考核满分数
        $this->ExerciseTime = 1800;//考核时间
    }

    /**
     * 接口,ASTR认证入口，获取认证相关的状态和信息
     * 资料填写  考核状态  认证状态
     * @throws \Exception
     */
    public function AstrXzdrStatus()
    {
        $zxdr_status = 0;
        //获取认证状态
        $AuthInfo = $this->getAuthStatus();
        //获取考核状态
        $zxdr = $ExerciseStatus = $this->getExerciseStatusNum(1);
        if ($zxdr['status'])
        {
            $zxdr_status = 1;
        }
        if (!$AuthInfo)
        {
            $AuthInfo['status'] = 0;
        }
        $data = [
            'video' => '',
            'auth_status' => $AuthInfo['status'],
            'zxdr_status' => $zxdr_status
        ];

        return show(config('code.success'), '获取成功', $data);
    }

    /**
     * 接口,咨询师认证状态
     * @return Json
     * @throws \Exception
     */
    public function AuthStatus()
    {
        //获取认证状态
        $AuthInfo = $this->getAuthStatus();
        //用户未填写信息
        $step = 0;
        //提示语初始化
        $auth_tips = '';
        $exercise = [];
        $divi_status = 0;
        $astr_status = 0;
        //标签初始化
        $tag = [
            'name' => '',
            'id' => 0,
            'status' => 0
        ];
        //认证信息初始化
        $auth_info = [
            'name' => '',
            'telphone' => '',
            'id_number' => '',
            'nickname' => '',
            'left_pic' => '',
            'right_pic' => '',
            'certificate_pic' => ''
        ];

        //用户填写信息后，进入考核页
        if ($AuthInfo)
        {
            $step = 1;
            //获取所有考核类型信息
            $ExerciseTypeInfo = $this->getExerciseTypeInfo();
            if ($ExerciseTypeInfo)
            {
                foreach ($ExerciseTypeInfo as $exercise_type)
                {
                    $exercise_status = $this->getExerciseStatusNum($exercise_type['id']);
                    switch ($exercise_type['id'])
                    {
                        case 1:
                            $divi_status = $exercise_status['status'] ?: 0;
                            break;
                        case 2:
                            $astr_status = $exercise_status['status'] ?: 0;
                            break;
                    }
                    $exercise[] = [
                        'status' => $exercise_status['status'],
                        'num' => $exercise_type['num'],
                        'pid' => $exercise_type['id'],
                        'time' => $exercise_type['time'],
                        'exercise_num' => $this->ExerciseNum - $exercise_status['num']
                    ];
                }
            }
            //考核全部通过后，进入认证页
            if ($divi_status && $astr_status)
            {
                $step = 2;
                //认证未通过，添加提示语
                if ($AuthInfo['status'] == 3)
                {
                    $auth_tips = '很遗憾，您未通过审核认证，请重新编辑认证信息';
                }
                $aliOss = AliOss::getInstance();
                $AuthInfo['left_pic'] = $aliOss->getAuth($AuthInfo['left_pic']);
                $AuthInfo['right_pic'] = $aliOss->getAuth($AuthInfo['right_pic']);
                $AuthInfo['certificate_pic'] = $aliOss->getAuth($AuthInfo['certificate_pic']);
                $auth_info = [
                    'name' => $AuthInfo['name'],
                    'telphone' => $AuthInfo['telphone'],
                    'id_number' => $AuthInfo['id_number'],
                    'nickname' => $AuthInfo['nickname'],
                    'left_pic' => $AuthInfo['left_pic'],
                    'right_pic' => $AuthInfo['right_pic'],
                    'certificate_pic' => $AuthInfo['certificate_pic']
                ];
            }
        } else
        {
            $tags = [];
            //获取擅长领域标签
            $tag_info = $this->getTagInfo(1);
            if ($tag_info)
            {
                $auth_area = $AuthInfo['area_ids'] ? explode(',', $AuthInfo['area_ids']) : [];
                $tag_status = 0;
                foreach ($tag_info as $tag)
                {
                    if (in_array($tag['id'], $auth_area))
                    {
                        $tag_status = 1;
                    }
                    $tags[] = [
                        'name' => $tag_info['name'],
                        'id' => $tag_info['id'],
                        'status' => $tag_status
                    ];
                }
            }
        }
        $arr = [
            'auth_status' => $AuthInfo['status'] ?? 0,
            'step' => $step,
            'exercise' => $exercise,
            'auth_tips' => $auth_tips,
            'area_list' => $tag,
            'auth_info' => $auth_info
        ];
        return show(config('code.success'), '获取成功', $arr);
    }

    /**
     * 接口,咨询师添加认证
     * 测评通过后才可认证
     * @return Json
     * @throws \Exception
     */
    public function Auth()
    {
        //后端判断新增/编辑
        $param = $this->request->only(['name', 'telphone', 'id_number', 'left_pic', 'right_pic', 'area_ids', 'nickname', 'certificate_pic']);

        $validate = validate('Counselor');

        if ($validate->scene('auth')->check($param) !== true)
        {
            return show(config('code.error'), $validate->getError());
        }
        $divi_status = $this->getExerciseStatusNum(1);
        $astr_status = $this->getExerciseStatusNum(2);

        if ($divi_status['status'] && $astr_status['status'])
        {
            //检查认证信息是否有重复
            $this->checkAuth($this->user['id'], $param);
            //提交认证
            $res = (new ZlAstrInfoCheck())->saveAuth($this->user['id'], $param);
            if ($res)
            {
                return show(config('code.success'), '保存成功', [
                    'status' => 1,
                    "title" => "已提交，待审核",
                    "msg" => "您的资料已提交成功，我们将尽快审核，预计5个工作日反馈结果，请随时留意软件消息",
                    "tips" => "如资料有误，"
                ]);
            } else
            {
                return show(config('code.error'), '认证失败，请稍后重试');
            }
        }
        return show(config('code.error'), '通过占星和提问测评后,才可认证');
    }

    /**
     * 接口,咨询师编辑认证
     * 测评通过后才可认证
     * @return Json
     * @throws \Exception
     */
    public function AuthUpdate()
    {
        //后端判断新增/编辑
        $param = $this->request->only(['name', 'telphone', 'id_number', 'left_pic', 'right_pic', 'area_ids', 'nickname', 'certificate_pic']);

        $validate = validate('Counselor');

        if ($validate->scene('auth')->check($param) !== true)
        {
            return show(config('code.error'), $validate->getError());
        }
        $divi_status = $this->getExerciseStatusNum(1);
        $astr_status = $this->getExerciseStatusNum(2);

        if ($divi_status['status'] && $astr_status['status'])
        {
            //检查认证信息是否有重复
            $this->checkAuth($this->user['id'], $param);
            //提交认证
            $res = (new ZlAstrInfoCheck())->updateAuth($this->user['id'], $param);
            if ($res)
            {
                return show(config('code.success'), '保存成功', [
                    'status' => 1,
                    "title" => "已提交，待审核",
                    "msg" => "您的资料已提交成功，我们将尽快审核，预计5个工作日反馈结果，请随时留意软件消息",
                    "tips" => "如资料有误，"
                ]);
            } else
            {
                return show(config('code.error'), '认证失败，请稍后重试');
            }
        }
        return show(config('code.error'), '通过占星和提问测评后,才可认证');
    }

    /**
     * 接口，开始认证
     * @return Json
     * @throws \Exception
     */
    public function StartAuth()
    {
        $AuthInfo = $this->getAuthStatus();
        if (!$AuthInfo)
        {
            return show(config('code.error'), '您未填写认证信息，请前去填写');
        }
        $DiviExererciseStatus = $this->getExerciseStatusNum(1);
        $AstrExererciseStatus = $this->getExerciseStatusNum(2);
        if (!$DiviExererciseStatus['status'] || !$AstrExererciseStatus['status'])
        {
            return show(config('code.error'), '通过占星和提问测评后,才可认证');
        }
        (new ZlAstrInfoCheck())->updateAuth($this->user['id'], ['status' => 1]);

        return show(config('code.success'), '操作成功');
    }

    /**
     * 接口，测评类型及状态
     * @return Json
     * @throws \Exception
     */
    public function ExamineTypeStatus()
    {
        $pid = input('param.pid');
        //获取考核类型信息
        $ExerciseType = $this->getExerciseTypeInfo();
        //获取考核通过状态
        $ExerciseStatus = $this->getExerciseStatusNum($pid);
        $arr = [
            'p_title' => '',
            'p_des' => '',
            'p_img' => '',
            'test_time' => '',
            'p_num' => '',
            'test_num' => '',
            'msg' => ''
        ];
        $num = $this->ExerciseNum - $ExerciseStatus['num'];
        if ($num <= 0)
        {
            $tips = '您本周的考核次数已用完，请下周继续努力';
        } else
        {
            $tips = '';
        }
        if ($ExerciseType)
        {
            foreach ($ExerciseType as $exercise_type)
            {
                if ($exercise_type['id'] == $pid)
                {
                    $arr = [
                        'p_title' => $exercise_type['name'],
                        'p_des' => $exercise_type['description'],
                        'p_img' => $exercise_type['img'],
                        'test_time' => $exercise_type['time'],
                        'p_num' => $exercise_type['num'],
                        'test_num' => $num,
                        'msg' => $tips
                    ];
                    break;
                }
            }
        }
        return show(config('code.success'), '获取成功', $arr);
    }

    /**
     * 接口，提交测评
     * pid 【1=>达人 2=>占星  3=>提问】
     * @return Json
     * @throws ApiException
     * @throws \Exception
     */
    public function SubmitExamine()
    {
        $param = $this->request->only(['pid', 'content']);

//        $validate = validate('Counselor');
//
//        if ($validate->scene('SubmitExamine')->check($param) !== true)
//        {
//            return show(config('code.error'), $validate->getError());
//        }
        $uid = $this->user['id'];
        $Exercise = new ZlAstrExercise();
        //获取剩余考试时间
        $exercise_time = $this->getTimeRemaining($param['pid']);
        //获取考核类型信息
        $ExerciseType = $this->getExerciseTypeInfo()[$param['pid']];
        if ($exercise_time === false)
        {
            return show(config('code.error'), '回答超时,请重新考核');
        }
//        $content = json_decode($param['content'], true);
        $content = $param['content'];

        $time = time();

        if ($content)
        {
            $ids = [];
            foreach ($content as $c)
            {
                $ids[] = $c['id'];
                $user_answer[$c['id']] = $c['answer'];
            }
            //获取当前提交的习题信息
            $exercise = $Exercise->batchGetInfoByIds($ids, ['id', 'title', 'title_img', 'option_a', 'option_b', 'option_c', 'option_d', 'answer', 'option_type']);
            if ($exercise === false)
            {
                return show(\config('code.error'), $Exercise->getError());
            }
            //总分数
            $total = $this->ExerciseTotalScore;
            //总题数
            $num = $ExerciseType['num'];
            //最终用户得分
            $final_score = 0;
            //答对的题目数
            $total_num = 0;

            //②对比习题获取分数
            if (is_array($exercise) && !empty($exercise))
            {
                //每题平均分
                $average_score = $total / $num;

                foreach ($exercise as $ex)
                {
                    //全部答对得分
                    if (strcasecmp($ex['answer'], $user_answer[$ex['id']]) == 0)
                    {
                        $final_score += $average_score;
                        $total_num += 1;
                    }
                }
            }
            // 写入答题记录
            $record_data = [
                'uid' => $uid,
                'content' => json_encode($content, true),
                'grade' => $final_score,
                'cet_id' => $param['pid'],
                'exercise_time' => $time,
                'create_time' => $time,
                'max_time'=>$ExerciseType['answer_time']
            ];
            $ExerciseRecordModel = new ZlAstrExerciseRecord();
            //保存答题记录
            $ExerciseRecordModel->saveUserExerciseRecord($uid, $param['pid'], $record_data);

            //更新咨询师等级和状态
            if ($final_score >= $this->ExerciseScore)
            {   // 分数达标  更新测评状态
                $result = 1; // 通过
                //保存答题结果
                $status_data = [
                    'uid' => $uid,
                    'astr_level' => $time,
                    'is_zxdr' => $time,
                    'create_time' => 0,
                ];
                switch ($param['pid'])
                {
                    case 1:
                        $typeName = '达人';
                        break;
                    case 2:
                        $typeName = '占星师';
                        break;
                    case 3:
                        $typeName = '提问师';
                        break;
                    default :
                        $typeName = '';
                        break;
                }
                $tips = '恭喜你通过了' . $typeName . '考核！\n只要再通过实名认证后你就是' . $typeName . '啦！';
                //新增
                (new ZlAstr())->SaveAstrLevel($uid, $status_data);
            } else
            {
                $result = 2;
                $tips = '成绩大于' . $this->ExerciseScore . '分才能通过测试！\n加油哦~';
            }

            //测评超时
            if ($ExerciseType === false)
            {
                $result = 3;
            }
            //默认考试次数
            $exercise_num = ['一', '两'];

            if ($ExerciseType['test_num'] == 0)
            {
                $title = '本周您的测评机会已用完,请下周继续努力';
            } else
            {
                $title = '本周您还有' . $exercise_num[$ExerciseType['test_num'] - 1] . '次机会';
            }

            $data = [
                'grade' => round($final_score, 0),
                'flag' => $result,
                'exercise_tips' => $title,
                'total_num' => $num,
                'success_num' => $total_num,
                'tips' => $tips,
                'is_check' => 0
            ];

            return show(config('code.success'), '提交成功', $data);
        }
    }

    /**
     * 接口，测评题目内容
     * @return Json
     * @throws \Exception
     */
    public function ExamineContent()
    {
        $param = $this->request->only(['pid']);

        $validate = validate('Counselor');
        if ($validate->scene('ExamineContent')->check($param) !== true)
        {
            return show(config('code.error'), $validate->getError());
        }
        //缓存答题开始时间
        Cache::set($this->user['id'] . '_astr_exercise_' . $param['pid'], time(), $this->ExerciseTime);
        //缓存今日答题次数
        (new ZlAstrExerciseRecord())->SaveUserExerciseRecordNum($this->user['id'], $param['pid']);
        //获取考核状态和次数
        $ExerciseStatus = $this->getExerciseStatusNum($param['pid']);
        if ($ExerciseStatus['status'])
        {
            return show(config('code.erre'), '您已通过当前考试');
        }
        if ($this->ExerciseNum - $ExerciseStatus['num'] < 0)
        {
            return show(config('code.error'), '您本周考核机会已用完，请下周继续努力');
        }
        //获取考核内容
        $exercise = $this->getExerciseInfo($param['pid']);

        foreach ($exercise as $k => $ex)
        {
            $exercise[$k]['answer'] = [
                $ex['option_a'],
                $ex['option_b'],
                $ex['option_c'],
                $ex['option_d'],
            ];
            unset($exercise[$k]['option_a']);
            unset($exercise[$k]['option_b']);
            unset($exercise[$k]['option_c']);
            unset($exercise[$k]['option_d']);
            unset($ex['answer']);
        }
        $arr = [
            'total' => count($exercise),
            'exercise_content' => $exercise
        ];
        return show(config('code.success'), '获取成功', $arr);
    }

    /**
     * 接口，答题剩余时间
     * @return Json
     * @throws \Exception
     */
    public function TimeRemaining()
    {
        $param = $this->request->only(['type']);
        $time = $this->getTimeRemaining($param['type']);

        if ($time === false)
        {
            return show(config('code.success'), '回答超时,请重新考核', ['time' => 0]);
        }

        return show(config('code.success'), '获取成功', ['time' => $time]);
    }

    /**
     * 咨询师主页信息接口
     * @return Json
     * @throws ApiException
     * @throws \Exception
     */
    public function CounselorHome()
    {
        $param = $this->request->only(['cid']);

        $validate = validate('Counselor');

        if ($validate->scene('CounselorHome')->check($param) !== true)
        {
            return show(config('code.error'), $validate->getError());
        }

        $uid = $this->user['id'];
        $ZhunleCounselor = new ZhunleCounselor();
        $CounselorAnswer = new ZhunleCounselorAnswer();
        $Recode = new Recode();
        $Counselor = $ZhunleCounselor->getInfoById($param['cid']);
        if ($Counselor === false)
        {
            return show(config('code.error'), $ZhunleCounselor->getError());
        }
        if ($Counselor)
        {
            $SelfInfo = $Recode->getSelfRecode(['uid' => $uid]);
            $RecodeInfo = $Recode->getRecodeWithAstro(['id' => $SelfInfo['id']]);
            //获取咨询师全部回答数
            $AllAnswerNum = $CounselorAnswer->getCountAllAnswer($param['cid']);
            if ($AllAnswerNum === false)
            {
                return show(config('code.error'), $CounselorAnswer->getError());
            }
            //获取咨询师被采纳的回答数
            $AcceptAnswerNum = $CounselorAnswer->getCountAcceptAnswer($param['cid']);
            if ($AcceptAnswerNum === false)
            {
                return show(config('code.error'), $CounselorAnswer->getError());
            }
            //获取最多的五个评价标签
            $tags = ZhunleCommentTag::getCounselorComment($param['cid']);

            if ($AllAnswerNum)
            {
                $accept = round($AcceptAnswerNum / $AllAnswerNum, 2) * 100;
            } else
            {
                $accept = 0;
            }

            if ($uid == $Counselor['uid'])
            {
                $is_me = 1;
            } else
            {
                $is_me = 0;
            }
            $arr = [
                'avatar' => $Counselor['avatar'],
                'nickname' => $Counselor['nickname'],
                'sex' => $Counselor['sex'],
                'sun' => $RecodeInfo['sun'],
                'moon' => $RecodeInfo['moon'],
                'asc' => $RecodeInfo['asc'],
                'divination_integral' => $Counselor['divination_integral'],
                'stargazer_integral' => $Counselor['stargazer_integral'],
                'star_level' => $Counselor['star_level'],
                'grab_num' => $Counselor['grab_num'],
                'state' => $Counselor['state'],
                'divination_level' => $Counselor['divination_level'],
                'stargazer_level' => $Counselor['stargazer_level'],
                'divination_price' => $Counselor['divination_price'],
                'stargazer_price' => $Counselor['stargazer_price'],
                'intro' => $Counselor['intro'],
                'is_me' => $is_me,
                'accept' => $accept . '%',
                'user_comment' => array_values($tags)
            ];
            return show(config('code.success'), '成功', $arr);
        } else
        {
            return show(config('code.error'), '当前咨询师不存在');
        }
    }

    /**
     * 获取用户认证状态
     * @throws \Exception
     */
    public function getAuthStatus()
    {
        $AstrInfoCheckModel = new ZlAstrInfoCheck();
        $data = $AstrInfoCheckModel->UserAstrInfo($this->user['id'], ['id', 'status', 'area_ids']);
        return $data;
    }

    /**
     * 获取所有考核类型信息
     * @throws \Exception
     */
    public function getExerciseTypeInfo()
    {
        $ExerciseTypeModel = new ZlAstrExerciseType();
        $data = $ExerciseTypeModel->getExerciseTypeInfo();

        return $data;
    }

    /**
     * 获取类型下的考核题目信息
     * @throws \Exception
     */
    public function getExerciseInfo($type)
    {
        $ExerciseModel = new ZlAstrExercise();
        $data = $ExerciseModel->getExerciseInfo($type);

        return $data;
    }

    /**
     * 获取用户考核状态和考核次数
     * @param $type //【1=>达人 2=>占星  3=>提问】
     * @throws \Exception
     */
    public function getExerciseStatusNum($type)
    {
        $ExerciseRecordModel = new ZlAstrExerciseRecord();
        $arr = [];
        $arr['status'] = $ExerciseRecordModel->getUserExerciseRecordStatus($this->user['id'], $type); //number
        $arr['num'] = $ExerciseRecordModel->getUserExerciseRecordNum($this->user['id'], $type); //number
        return $arr;
    }

    /**
     * 获取标签信息
     * @throws \Exception
     */
    public function getTagInfo($type)
    {
        $TagModel = new ZlTag();
        $data = $TagModel->getTagId($type);
        return $data;
    }

    /**
     * 获取测评剩余时间
     * @param array $map
     * @return float|int|Json|array
     * @throws \Exception
     */
    public function getTimeRemaining($pid)
    {
        //计算答题时间是否超时
        $start_time = Cache::get($this->user['id'] . '_astr_exercise_' . $pid);
        $time = time() - $start_time;
        if ($time > $this->ExerciseTime)
        {
            return false;
        }
        return $time - $this->ExerciseTime;
    }

    /**
     * 检查认证信息是否有重复
     * @param $uid
     * @param array $data
     * @return bool|Json
     */
    public function checkAuth($uid, $data = [])
    {
        $CounselorAuth = new ZlAstrInfoCheck();
        //判断所有认证是否有重复的
        $AllAuthInfo = $CounselorAuth->getAuthCheck($uid, $data['id_number'], $data['nickname'], $data['telphone']);

        if ($AllAuthInfo === false)
        {
            return show(config('code.error'), $CounselorAuth->getError());
        }
        if ($AllAuthInfo)
        {
            if ($AllAuthInfo['uid'] == $uid)
            {
                return show(config('code.error'), '当前用户已认证，不可重复提交认证');
            }

            if ($AllAuthInfo['id_number'] == $data['id_number'])
            {
                return show(config('code.error'), '当前身份证已被注册');
            }

            if ($AllAuthInfo['nickname'] == $data['nickname'])
            {
                return show(config('code.error'), '当前咨询师名称已被注册');
            }

            if ($AllAuthInfo['telphone'] == $data['telphone'])
            {
                return show(config('code.error'), '当前手机号已被注册');
            }
        }

        return true;
    }
}
